﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using UofCASE.AgileProductLinerDSL.Nant.Tasks.visualizing;

namespace UofCASE.AgileProductLinerDSL.Nant.Tasks.Models
{
    public class ProductLinerSet
    {
        public FileInfo SolutionRoot { get; private set; }
        public FileInfo ProductLinerDir { get; private set; }
        public string AssemblyPath { get; private set; }
        public FileInfo CollectionPlan { get; private set; }
        IList<Feature> features;
        IList<Platform> platforms;

        public ProductLinerSet(String solutionRoot, String productLinerDir, String assemblyPath) 
            : this(solutionRoot, productLinerDir, assemblyPath, solutionRoot + "/CollectionPlan.xml")
        {}
        

        public ProductLinerSet(String solutionRoot, String productLinerDir, String assemblyPath, String collectionPlan)
        {
            this.SolutionRoot = new FileInfo(solutionRoot);
            this.ProductLinerDir = new FileInfo(productLinerDir);
            this.AssemblyPath = assemblyPath;
            this.CollectionPlan = new FileInfo(collectionPlan);
            features = new List<Feature>();
            platforms = new List<Platform>();
        }

        public void AddFeature(Feature f){
            features.Add(f);
        }

        public void AddPlatform(Platform p){
            p.owner = this;
            platforms.Add(p);
        }

        public void AddTest(Feature f, Platform p, Test t)
        {
            f.AddToPlatform(p, t);
        }

        public void AddPlatform(Platform p, IList<String> configurations)
        {
            AddPlatform(p);
            foreach (String config in configurations)
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<string>));
                FileStream fs = new FileStream(config, FileMode.Open, FileAccess.Read);
                IList<String> includedFeatures = xmlSerializer.Deserialize(fs) as List<string>;
                foreach (String featureName in includedFeatures)
                {
                    Feature f = new Feature(featureName);
                    AddFeature(f);

                    IList<String> childTests = new List<string>();
                    String featureModel = Path.GetFileNameWithoutExtension(config);
                    FeatureModel model = Utils.LoadFeatureModel(ProductLinerDir + "/FeatureModels/" + featureModel + ".fm");
                    UofCASE.AgileProductLinerDSL.Feature feature = model.GetFeature(shortName(featureName));

                    //questionable if this line will work correctly, it is strange.
                    if (feature != null)
                        foreach (UofCASE.AgileProductLinerDSL.Test test in feature.getChildTests())
                            childTests.Add(test.RelativePath);
                    
                    foreach (String s in childTests)
                    {
                        AddTest(f, p, new Test(new FileInfo(SolutionRoot + "/" + s)));
                    }
                }
            }
        }

        public void RunTestsFor(Platform p)
        {
            foreach(ITest test in p){
                test.Run();
            }
        }

        private string shortName(string name)
        {
            int i;
            for (i = name.Length - 1; i >= 0; i--)
            {
                if (name[i] == '\\') break;
            }
            i++;

            return name.Substring(i);
        }

        internal bool GetPassed(Platform windows)
        {
            int index = platforms.IndexOf(windows);
            return platforms[index].Passed;
        }

        internal int GetPassed(Feature feature)
        {
            int index = features.IndexOf(feature);
            if (index < 0) return -1;
            return features[index].Passed();
        }

        internal String style(bool success, bool failure){
            String style = "background:";
            if (success)
            {
                style += "#AAFFAA;";
            }
            else if (failure)
            {
                style += "#FFAAAA;";
            }
            else
            {
                style += "#FFFFFF;";
            }
            return style;
        }

        public String ToHtml()
        {
            XmlElement table = new XmlElement("table", "border", "1");
            XmlElement headerRow = new XmlElement("tr");
            XmlElement cellx0y0 = new XmlElement("td");
            cellx0y0.AddChildElement(new WhiteSpaceTextElement());
            headerRow.AddChildElement(cellx0y0);
            foreach (Platform platform in platforms)
            {
                XmlElement platformCell = new XmlElement("td");
                platformCell.AddChildElement(new TextElement(platform.Name));
                headerRow.AddChildElement(platformCell);
            }
            table.AddChildElement(headerRow);

            //feature rows
            foreach (Feature feature in features)
            {
                XmlElement featureRow = new XmlElement("tr");

                XmlElement featureCell = new XmlElement("td");
                XmlElement featureBolding = new XmlElement("b");
                featureBolding.AddChildElement(new TextElement(feature.Name));
                featureCell.AddChildElement(featureBolding);
                featureRow.AddChildElement(featureCell);

                foreach (Platform platform in platforms)
                {
                    XmlElement resultCell = new XmlElement("td", "style", style(feature.Passed(platform), feature.Failed(platform)));
                    resultCell.AddChildElement(new WhiteSpaceTextElement());
                    featureRow.AddChildElement(resultCell);

                    table.AddChildElement(featureRow);
                }

                foreach(TestKey key in feature.TestKeys())
                {
                    XmlElement testRow = new XmlElement("tr");
                    XmlElement testCell = new XmlElement("td");
                    testCell.AddChildElement(new TextElement(key.TestName));
                    testRow.AddChildElement(testCell);

                    foreach (Platform platform in platforms)
                    {
                        ITest test = feature.Test(key, platform);
                        XmlElement resultCell = new XmlElement("td", "style", style(test != null && test.Passed, test != null && test.Failed));
                        resultCell.AddChildElement(new WhiteSpaceTextElement());
                        testRow.AddChildElement(resultCell);
                    }

                    table.AddChildElement(testRow);
                }

            }
            return table.render();
        }
    }
}
